import 'dart:async';

import 'package:biometrics/components/method.dart';
import 'package:biometrics/opencv/detector.dart';
import 'package:flutter/material.dart';
import 'package:biometrics/opencv/recognizer.dart';

typedef FeatureList = List<double>;
final Recognizer recognizer = Recognizer();
final Detector detector = Detector();

enum TipLevel {
  info(Colors.black),
  warning(Colors.orange),
  error(Colors.red),
  success(Colors.green),
  ;

  const TipLevel(this.color);
  final Color color;
}

enum ControllerType {
  detect,
  recognize,
  ;
}

// 探测、识别情景控制器
class Controller {
  // 识别特征值平均值
  FeatureList? _avgDetectFeature;
  // 计算平均值所需要的特征值数量
  final featureCount = 5;
  // 提示列表
  final Map<int, Text> _texts = {};
  int _id = 0;
  // 特征值组，用于区分不同的人脸
  final List<List<FeatureList>> _featuresGroup = [];
  // 识别任务完成开关
  Completer<FeatureList> _detectCompleter = Completer();
  // 场景类型
  final ControllerType type;
  final List<Function(FeatureList)> _detectCallback = [];
  final List<Function(String?)> _taskCallback = [];
  final int? faceId;

  final Method method = Method();

  List<Text> get tips => _texts.values.toList();
  FeatureList? get avgDetectFeature => _avgDetectFeature;
  bool get isCompleted => _detectCompleter.isCompleted;

  Controller(this.type, {this.faceId});

  /// 重置控制器
  void reset() {
    _texts.clear();
    _id = 0;
    _featuresGroup.clear();
    _detectCompleter = Completer();
    _avgDetectFeature = null;
  }

  void callWhenDetectComplete(Function(FeatureList) callback) {
    _detectCallback.add(callback);
  }

  void callWhenTaskComplete(Function(String?) callback) {
    _taskCallback.add(callback);
  }

  // 添加提示，返回该提示id
  int addTip(String tip, {TipLevel level = TipLevel.info}) {
    final id = _id;
    _texts[id] = Text(
      tip,
      style: TextStyle(color: level.color, fontSize: 16),
    );
    _id++;

    return id;
  }

  // 根据id删除提示
  void removeTip(int? index) {
    if (index == null) return;
    _texts.remove(index);
  }

  // 添加识别特征，
  void updateDetectFeature(FeatureList newfeature) async {
    if (_detectCompleter.isCompleted) return;
    int n = 0;
    while (n < _featuresGroup.length) {
      List<FeatureList> group = _featuresGroup[n];
      final ret = await recognizer.matchFaces(newfeature, group);

      // 任务繁忙，重新尝试
      if (ret == null) continue;

      // 匹配成功，添加到当前组
      if (ret) {
        group.add(newfeature);

        // 检查是否满足数量
        if (group.length >= featureCount) {
          _avgDetectFeature = _computeAverageFeature(group);
          // 匹配完成，返回结果
          _detectCompleter.complete(_avgDetectFeature);
          for (var cb in _detectCallback) {
            cb.call(_avgDetectFeature!);
          }
          addTip("开始${type == ControllerType.recognize ? "比对" : "写入"}人脸特征");
          final task = type == ControllerType.recognize
              ? method.matchFaceFeature(_avgDetectFeature!, id: faceId)
              : method.writeFaceFeature(_avgDetectFeature!, faceId);

          task.then((v) {
            addTip("交互结束，结果为 $v");
            for (var cb in _taskCallback) {
              cb.call(v.toString());
            }
          }).catchError((v) {
            addTip("交互失败 $v");
            for (var cb in _taskCallback) {
              cb.call(null);
            }
          });
        }
        return;
      }

      n++;
    }
    addTip("新增人脸组");
    // 所有组都未匹配成功，为新的人脸特征值
    _featuresGroup.add([newfeature]);
  }

  List<double> _computeAverageFeature(List<List<double>> features) {
    final avgFeature = List<double>.filled(features[0].length, 0.0);
    for (var feature in features) {
      for (var i = 0; i < feature.length; i++) {
        avgFeature[i] += feature[i];
      }
    }
    return avgFeature.map((value) => value / features.length).toList();
  }
}
